package com.dimples.system.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dimples.common.constant.StrPool;
import com.dimples.common.entity.SecurityUser;
import com.dimples.common.exception.DataException;
import com.dimples.common.page.metadata.Page;
import com.dimples.common.service.DimplesJwtTokenServiceImpl;
import com.dimples.common.transport.QueryRequest;
import com.dimples.common.util.HttpContextUtil;
import com.dimples.common.util.SecurityContextUtil;
import com.dimples.system.entity.SysFile;
import com.dimples.system.entity.SysUser;
import com.dimples.system.entity.SysUserRole;
import com.dimples.system.mapper.SysUserMapper;
import com.dimples.system.service.SysDeptService;
import com.dimples.system.service.SysFileService;
import com.dimples.system.service.SysUserRoleService;
import com.dimples.system.service.SysUserService;
import com.dimples.system.vo.UserVO;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

import javax.annotation.Resource;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2021/7/18
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private final DimplesJwtTokenServiceImpl tokenService;

    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SysDeptService sysDeptService;
    @Resource
    private SysFileService sysFileService;

    @Override
    public Page<SysUser> findUser(SysUser sysUser, QueryRequest queryRequest) {
        Page<SysUser> page = new Page<>(queryRequest.getPageNumber(), queryRequest.getPageSize());
        page.setRecords(this.baseMapper.findUser(page, sysUser));
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveUser(SysUser sysUser) {
        if (ObjectUtil.isNotEmpty(this.getOne(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUsername, sysUser.getUsername())))) {
            throw new DataException(StrUtil.format("[ username = {} ]已存在", sysUser.getUsername()));
        }
        sysUser.setStatus(StrUtil.isBlank(sysUser.getStatus()) ? SysUser.STATUS_VALID : sysUser.getStatus());
        sysUser.setPassword(StrUtil.isBlank(sysUser.getPassword()) ? SysUser.DEFAULT_AVATAR : sysUser.getPassword());
        sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
        sysUser.setCreateTime(new Date());
        this.save(sysUser);
        if (ObjectUtil.isNotEmpty(sysUser.getRoleId())) {
            if (ObjectUtil.isEmpty(sysUserRoleService.getOne(
                    Wrappers.lambdaQuery(SysUserRole.class)
                            .eq(SysUserRole::getUserId, sysUser.getUserId())
                            .eq(SysUserRole::getRoleId, sysUser.getRoleId())))) {
                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setUserId(sysUser.getUserId());
                sysUserRole.setRoleId(sysUser.getRoleId());
                this.sysUserRoleService.save(sysUserRole);
            }
        }
    }

    @Override
    public void updateUser(SysUser sysUser) {
        if (ObjectUtil.isEmpty(sysUser.getUserId())) {
            throw new DataException(StrUtil.format("userId 不能为空"));
        }
        if (ObjectUtil.isEmpty(this.sysDeptService.getById(sysUser.getDeptId()))) {
            throw new DataException(StrUtil.format("[ deptId = {} ]不存在", sysUser.getDeptId()));
        }
        this.updateById(sysUser);
        SecurityUser securityUser = BeanUtil.copyProperties(sysUser, SecurityUser.class);
        SecurityContextUtil.refreshCache(tokenService, securityUser);
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @Override
    public void deleteUser(Long userId) {
        this.removeById(userId);
        this.sysUserRoleService.remove(Wrappers.lambdaUpdate(SysUserRole.class).eq(SysUserRole::getUserId, userId));
    }

    @Override
    public void deleteUsers(String userIds) {
        long[] ids = StrUtil.splitToLong(userIds, StrPool.COMMA);
        for (long id : ids) {
            deleteUser(id);
        }
    }

    @Override
    public UserVO getUser(Long userId) {
        return this.baseMapper.getUser(userId);
    }

    @Override
    public void updateUserPassword(String oldPassword, String newPassword) {
        if (StrUtil.equals(oldPassword, newPassword)) {
            throw new DataException("新密码不能和旧密码一致");
        }
        SysUser sysUser = this.getById(tokenService.getLoginUserFromToken(HttpContextUtil.getRequest()).getUserId());
        if (!passwordEncoder.matches(oldPassword, sysUser.getPassword())) {
            throw new DataException("旧密码错误");
        }
        SysUser userUpdate = new SysUser();
        userUpdate.setUserId(sysUser.getUserId());
        userUpdate.setPassword(passwordEncoder.encode(newPassword));
    }

    @Override
    public SecurityUser updateUserAvatar(String avatarId) {
        Long userId = tokenService.getLoginUserFromToken(HttpContextUtil.getRequest()).getUserId();
        SysUser user = new SysUser();
        SysFile file = this.sysFileService.getById(avatarId);
        user.setUserId(userId);
        user.setAvatar(file.getFileName());
        this.updateById(user);
        SecurityUser securityUser = new SecurityUser();
        securityUser.setAvatar(file.getFileName());
        SecurityContextUtil.refreshCache(tokenService, securityUser);
        return tokenService.getLoginUserFromToken(HttpContextUtil.getRequest());
    }

    @Override
    public SysUser findByName(String username) {
        return this.getOne(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUsername, username));
    }

    @Override
    public void register(String username, String password) {
        SysUser user = new SysUser();
        user.setPassword(passwordEncoder.encode(password));
        user.setUsername(username);
        user.setCreateTime(new Date());
        user.setStatus(SysUser.STATUS_VALID);
        user.setSsex(SysUser.SEX_UN_KNOW);
        user.setAvatar(SysUser.DEFAULT_AVATAR);
        user.setTheme(SysUser.THEME_BLACK);
        user.setDescription("注册用户");
        save(user);

        SysUserRole ur = new SysUserRole();
        ur.setUserId(user.getUserId());
        ur.setRoleId(SysUser.REGISTER_ROLE_ID);
        this.sysUserRoleService.save(ur);
    }
}
